CIでPrettier/ESLintを実行して違反時にWorkflowを失敗させる
こんにちは、CX事業本部 IoT事業部の若槻です。
PrettierとESLintは、JavaScript系のプロジェクトでよく使われる構文チェックツールです。
Prettierは主にコードのスタイルを整形するフォーマッターです。ESLintはコード内の不要な記述の削除を促すリンターです。両者は役割が異なる(重複する部分もありますが)ため一緒に使われることが多いです。
今回は、PrettierおよびESLintをCI上で実行して、違反時にWorkflowを失敗させる方法を確認してみました。
環境準備
今回はAWS CDKプロジェクト(TypeScript)で試してみます。
プロジェクトを作成します。
$ npx cdk init --language typescript
PrettierとESLintおよび周辺ライブラリをインストールします。
$ npm install -D \ prettier \ eslint \ eslint-config-prettier \ eslint-config-standard \ @typescript-eslint/eslint-plugin
PrettierとESLintがインストールできました。
$ npm ls --depth=0 ├── eslint@8.13.0 ├── prettier@2.6.2
その他ライブラリは次のような用途で入れています。
- eslint-config-prettierはPrettierとConflictするESLintのルールを無効にします。
- eslint-config-standardはShareable Config(.eslintrc)が使用可能になります。
- @typescript-eslint/eslint-pluginはESLintのTypeScript Pluginです。
.eslintrc.json
ファイルを作成して、ESLintのPrettierとの併用およびTypeScriptで利用するための設定を記述します。
{ "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier" ], "parser": "@typescript-eslint/parser", "parserOptions": { "project": "./tsconfig.json" }, "plugins": [ "@typescript-eslint" ] }
また.prettierrc.json
ファイルを作成して、Prettierのフォーマッティングルールを定義します。
{ "singleQuote": true, "trailingComma": "all", "tabWidth": 2 }
周辺ライブラリとしては他にもeslint-plugin-import
やeslint-plugin-node
、eslint-plugin-promise
などをよく導入しますが、今回は一旦ここまでとします。
CLI実行時のExit code
CI/CDツールではExit codeが0
以外の時にWorkflowの実行が失敗となります。まずはPrettierおよびESLintのCLI実行時のExit codeの仕様について確認してみます。
Prettier
Prettierでは--check
フラグを使用すれば、CLIコマンドの実行でファイルのフォーマットチェックができます。
フォーマットの違反が無ければExit codeは0
となります。
$ npx prettier --check lib Checking formatting... All matched files use Prettier code style! $ echo $? 0
違反があれば1
となります。
$ npx prettier --check lib Checking formatting... [warn] lib/aws-cdk-v2-project-stack.ts [warn] Code style issues found in the above file(s). Forgot to run Prettier? $ echo $? 1
ESLint
ESLintが検知する違反にはerrors
とwarning
の2種類があり、warning
のみ検知時にExit codeを0
とするには--max-warnings
の設定が必要です。
違反が無ければExit codeは0
となります。
$ npx eslint src --max-warnings=0 $ echo $? 0
違反があれば1
となります。warning
が一つ検知されています。
$ npx eslint lib --max-warnings=0 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-v2-project/lib/aws-cdk-v2-project-stack.ts 87:7 warning 'aaa' is assigned a value but never used @typescript-eslint/no-unused-vars ✖ 1 problem (0 errors, 1 warning) ESLint found too many warnings (maximum: 0). $ echo $? 1
CI上で実行してみる
prettier
とeslint
の実行コマンドをpackage.json
のscriptsに設定してプロジェクト上でコマンド実行できるようにします。
{ "scripts": { "format": "prettier --check './{bin,lib,src,tests}/**/*.{ts,tsx}'", "lint": "eslint './{bin,lib,src,tests}/**/*.{ts,tsx}' --max-warnings=0" } }
上述のコマンドをCI/CDツール(今回はGitHub Actions)のWorkflow fileに記述して実行されるようにします。
on: push: paths-ignore: - '**/*.md' jobs: integrate: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Cache CDK Dependency uses: actions/cache@v3 id: cache_cdk_dependency_id env: cache-name: cache-cdk-dependency with: path: node_modules key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }} restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}- - name: Install Dependency if: ${{ steps.cache_cdk_dependency_id.outputs.cache-hit != 'true' }} run: npm ci --no-audit --progress=false --silent - name: Lint & Format run: | npm run lint npm run format
Workflowを実行します。ESLintでリント違反となり、Workflowが失敗しました。
リント違反部分を修正し再度Workflowを実行します。次はPrettierでフォーマット違反となり、Workflowが失敗しました。
フォーマット違反を修正します。
$ npx prettier --write './{bin,lib,src,tests}/**/*.{ts,tsx}' bin/aws-cdk-v2-project.ts 294ms lib/aws-cdk-v2-project-stack.ts 31ms
再度Workflowを実行すると、今度はリントもフォーマットも違反無くパスし、Workflowが成功しました!
おわりに
PrettierおよびESLintをCI上で実行して、違反時にWorkflowを失敗させる方法を確認してみました。
huskyを使用してpre-commit時にフォーマット/リントを強制する宗派もありますが、私は今回のようなCI/CDツール上にオフロードする方が好みです。
参考
以上